package com.duojuhe.coremodule.system.service.impl;

import com.duojuhe.cache.SystemDictCache;
import com.duojuhe.common.annotation.DataScopeFilter;
import com.duojuhe.common.bean.DataScopeFilterBean;
import com.duojuhe.common.bean.UserTokenInfoVo;
import com.duojuhe.common.constant.DataScopeConstants;
import com.duojuhe.common.enums.SystemEnum;
import com.duojuhe.common.result.ErrorCodes;
import com.duojuhe.common.result.PageResult;
import com.duojuhe.common.result.ServiceResult;
import com.duojuhe.common.utils.page.PageHelperUtil;
import com.duojuhe.coremodule.BaseService;
import com.duojuhe.coremodule.chat.im.mapper.ChatUsersChatListMapper;
import com.duojuhe.coremodule.chat.im.mapper.ChatUsersFriendsApplyMapper;
import com.duojuhe.coremodule.system.entity.SystemDict;
import com.duojuhe.coremodule.system.entity.SystemMessage;
import com.duojuhe.coremodule.system.mapper.SystemMessageMapper;
import com.duojuhe.coremodule.system.pojo.dto.message.*;
import com.duojuhe.coremodule.system.service.SystemMessageService;
import com.duojuhe.websocket.EventCodes;
import com.duojuhe.websocket.subscriber.SendChatSubscribeUtil;
import com.duojuhe.websocket.subscriber.SubscribeHandleDto;
import com.duojuhe.websocket.subscriber.message.sendmsg.MessageUntreatedDto;
import com.duojuhe.websocket.subscriber.message.sendmsg.SystemSendMessageDto;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class SystemMessageServiceImpl  extends BaseService implements SystemMessageService {
    @Resource
    private SystemDictCache systemDictCache;
    @Resource
    private SendChatSubscribeUtil sendChatSubscribeUtil;
    @Resource
    private SystemMessageMapper systemMessageMapper;
    @Resource
    private ChatUsersChatListMapper chatUsersChatListMapper;
    @Resource
    private ChatUsersFriendsApplyMapper chatUsersFriendsApplyMapper;

    /**
     * 【分页查询】分页查询系统消息list
     * @param req
     * @return
     */
    @DataScopeFilter(dataScope = DataScopeConstants.SELF_DATA)
    @Override
    public ServiceResult<PageResult<List<QuerySystemMessagePageRes>>> querySystemMessagePageResList(QuerySystemMessagePageReq req) {
        PageHelperUtil.orderByAndStartPage(req, "createTime desc, messageId desc");
        List<QuerySystemMessagePageRes> list = systemMessageMapper.querySystemMessagePageResList(req);
        list.forEach(this::setHandleSystemMessageDictNameColor);
        return PageHelperUtil.returnServiceResult(req,list);
    }

    /**
     * 【统计未处理 数量】统计未读数量
     * @param dataScope
     * @return
     */
    @DataScopeFilter(dataScope = DataScopeConstants.SELF_DATA)
    @Override
    public ServiceResult<MessageNumRes> queryCountUntreatedSystemMessage(DataScopeFilterBean dataScope) {
        //当前登录用户id
        String userId = getCurrentLoginUserId();
        //返回对象
        MessageNumRes res = new MessageNumRes();
        //系统消息未读数量
        Integer systemMessageNum = systemMessageMapper.queryCountUntreatedSystemMessageByUserId(userId);
        //多聊未读消息
        Integer chatMessageNum = chatUsersChatListMapper.queryCountUntreatedChatMessageByUserId(userId);
        //好友申请数量
        Integer friendApplyNum = chatUsersFriendsApplyMapper.selectCountMyFriendApplyNumByUserId(userId);
        res.setSystemMessageNum(systemMessageNum);
        res.setChatMessageNum(chatMessageNum);
        res.setFriendApplyNum(friendApplyNum);
        return ServiceResult.ok(res);
    }

    /**
     * 【一键未处理】一键未处理
     * @param dataScope
     * @return
     */
    @DataScopeFilter(dataScope = DataScopeConstants.SELF_DATA)
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServiceResult updateAllSystemMessageHandleStatus(DataScopeFilterBean dataScope) {
        //当前登录人
        UserTokenInfoVo userTokenInfoVo = getCurrentLoginUserInfoDTO();
        BatchHandleSystemMessageReq batchHandleMessage = new BatchHandleSystemMessageReq();
        batchHandleMessage.setDataScopeFilter(dataScope.getDataScopeFilter());
        batchHandleMessage.setHandleStatusCode(SystemEnum.HANDLING_STATUS.PROCESSED.getKey());
        batchHandleMessage.setHandleTime(new Date());
        batchHandleMessage.setHandleUserId(userTokenInfoVo.getUserId());
        systemMessageMapper.updateAllSystemMessageHandleStatus(batchHandleMessage);

        // 异步发送未读消息总数
        handleSystemMessageUntreatedNum(userTokenInfoVo.getUserId());
        return ServiceResult.ok(ErrorCodes.SUCCESS);
    }

    /**
     * 【根据id设置未处理】根据id设置未处理
     * @param req
     * @return
     */
    @Override
    public ServiceResult updateSystemMessageHandleStatusByMessageId(SystemMessageIdReq req) {
        String messageId = req.getMessageId();
        SystemMessage systemMessageOld = systemMessageMapper.selectByPrimaryKey(messageId);
        if (systemMessageOld==null){
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        if (!SystemEnum.HANDLING_STATUS.PENDING.getKey().equals(systemMessageOld.getHandleStatusCode())){
            return ServiceResult.fail(ErrorCodes.NOT_REPEAT_PROCESS_ERROR);
        }
        //当前登录人
        UserTokenInfoVo userTokenInfoVo = getCurrentLoginUserInfoDTO();
        if (!systemMessageOld.getCreateUserId().equals(userTokenInfoVo.getUserId())){
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        SystemMessage systemMessage = new SystemMessage();
        systemMessage.setMessageId(messageId);
        systemMessage.setHandleStatusCode(SystemEnum.HANDLING_STATUS.PROCESSED.getKey());
        systemMessage.setHandleTime(new Date());
        systemMessage.setHandleUserId(userTokenInfoVo.getUserId());
        systemMessageMapper.updateByPrimaryKeySelective(systemMessage);

        // 异步发送未读消息总数
        handleSystemMessageUntreatedNum(systemMessageOld.getCreateUserId());
        return ServiceResult.ok(ErrorCodes.SUCCESS);
    }


    /**
     * 保存消息
     * @param systemMessage
     */
    @Override
    public void saveSystemSendMessage(SystemMessage systemMessage) {
        if (systemMessage==null || StringUtils.isBlank(systemMessage.getCreateUserId())){
            return;
        }
        //用户id
        String userId = systemMessage.getCreateUserId();
        //保存消息
        systemMessageMapper.insertSelective(systemMessage);
        // 异步发送未读消息总数
        handleSystemMessageUntreatedNum(userId);
    }


    /**
     * 处理用户未读消息数量发送
     * @param userId
     */
    private void handleSystemMessageUntreatedNum(String userId){
      try {
          if (StringUtils.isBlank(userId)){
              return;
          }
          //未读数量
          int untreatedNum = systemMessageMapper.queryCountUntreatedSystemMessageByUserId(userId);
          //构建消息对象
          String type = SystemEnum.UNTREATED_TYPE.UNTREATED_SYSTEM_MESSAGE.getKey();
          SystemSendMessageDto sendMessageDto = new SystemSendMessageDto(userId,new MessageUntreatedDto(untreatedNum,type));
          // 异步发送消息
          SubscribeHandleDto<SystemSendMessageDto> subscribeHandleDto = new SubscribeHandleDto<SystemSendMessageDto>();
          subscribeHandleDto.setEventType(EventCodes.EVENT_SYSTEM_MESSAGE.getEvent());
          subscribeHandleDto.setMessageData(sendMessageDto);
          sendChatSubscribeUtil.sendSystemSubscribeMessage(subscribeHandleDto);
      }catch (Exception e){
          log.error("【发送用户未读系统消息总数出现异常】,用户ID:{}",userId,e);
      }
    }

    /**
     * 处理返回值的数据字典
     * @param res
     */
    private void setHandleSystemMessageDictNameColor(QuerySystemMessagePageRes res) {
        if (res==null){
            return;
        }
        SystemDict handleStatusCode = systemDictCache.getSystemDictByDictCode(res.getHandleStatusCode());
        res.setHandleStatusName(handleStatusCode.getDictName());
        res.setHandleStatusColor(handleStatusCode.getDictColor());

        SystemDict messageTypeCode = systemDictCache.getSystemDictByDictCode(res.getMessageTypeCode());
        res.setMessageTypeName(messageTypeCode.getDictName());
        res.setMessageTypeColor(messageTypeCode.getDictColor());
    }
}
